#include "string.h"
#include "stdlib.h"
#include "stdio.h"

// USER API
#include "tuya_user_api.h"
#include "tuya_comm.h"

// OS API
#include "tal_mutex.h"
#include "tal_semaphore.h"
#include "tal_queue.h"
#include "tal_thread.h"
#include "tal_sw_timer.h"
#include "xy_api.h"

#include "tkl_i2c.h"
#include "tkl_adc.h"
#include "tkl_gpio.h"

// driver
#include "ssd1306.h"
#include "iot_board_sensor.h"

static THREAD_HANDLE iot_board_sensor_thread = NULL;
static QUEUE_HANDLE iot_board_sensor_queue = NULL;
static TIMER_PARAM_S iot_board_sensor_timer;

iot_board_sensor nbiot_club_sensor;
static bool fota_running = false;

system_event_t tuya_system_event;
static MUTEX_HANDLE     ty_sensor_mutex = NULL;   //mutex lock


void event_ui_process(uint8_t* ui_log)
{
    OLED_DrawStr(8, UI_EVENT_LINE_CONT, ui_log);
}

void ota_ui_process(bool fota_run, uint8_t precent)
{
    if(precent > 100) return;

    OLED_DrawStr(0, 36, "                   ");
    uint8_t display_buff[25];
    sprintf(display_buff, fota_run ? " FOTA:          %d%% " : " SCMA:          %d%% ", precent);
    OLED_DrawStr(0, 46, display_buff);
    OLED_DrawStr(1, 56, "[                   ]");

    int status = precent/7;
    for(int i =1; i< status; i++)
    {
        OLED_DrawStr(8*i,56,"=");
    }
    OLED_DrawStr(8*status+1,56,">");
}

//UI界面显示任务
static void iot_board_sensor_task(void *pvParameters)
{
    iot_board_event_t queue_rcv;
    USER_API_LOGD("iot board sensor task create success !!!");

    while (1)
    {
        // 消息队列接收
        int ret = tal_queue_fetch(iot_board_sensor_queue, &queue_rcv, 0xFFFFFFFF);
        switch (queue_rcv.event_id)
        {
        case SYSTEM_EVENT_ID_CARD:
            event_ui_process("simcard ready      ");
            break;

        case SYSTEM_EVENT_NETWORK_READY:
            event_ui_process("network ready      ");
            break;

        case EVENT_LWM2M_CONNECTED:
            event_ui_process("lwm2m connect      ");
            break;

        case EVENT_LWM2M_READY:
            event_ui_process("lwm2m ready        ");
            break;

        case EVENT_LWM2M_UPDATE_SUCCESS:
            event_ui_process("lwm2m update y     ");
            break;

        case EVENT_LWM2M_RESPONSE_SUCCESS:
            event_ui_process("lwm2m response succ");
            break;

        case EVENT_LWDP_PACKET_SEND:
            event_ui_process("lwdp pack send     ");
            break;

        case EVENT_POWERKEY_PRESS:
            break;

        case EVENT_DEVICE_BIND_ON:
            event_ui_process("device bind        ");
            event_ui_process(tuya_user_api_is_dev_binded() ? "bind:yes" : "bind:no");
            break;

        case EVENT_DEVICE_UNBIND_ON:
            event_ui_process("device unbind      ");
            event_ui_process(tuya_user_api_is_dev_binded() ? "bind:yes" : "bind:no");
            break;

        case SYSTEM_EVENT_GOING_SLEEP:
            tal_sw_timer_stop(iot_board_sensor_timer.timerid);
            event_ui_process("I wlii going sleep...");
            tkl_i2c_deinit(0);
            //关闭OLED 电源，准备进入超低功耗
            ssd1306_power(false); 
            break;
        case IOT_OTA_EVENT_DOWNLOAD_START:
            event_ui_process("fota download start ");
            fota_running = true;
            break;

        case IOT_OTA_EVENT_DONWLOAD_FAIL:
            event_ui_process("fota download fail ");
            break;

        case IOT_OTA_EVENT_DOWNLOAD_COMPLETE:
            event_ui_process("fota download succ");
            break;

        case IOT_OTA_EVENT_SCHEMA_DONWLOAD_START:
            event_ui_process("schema download start");
            break;

        case IOT_OTA_EVENT_SCHEMA_DONWLOAD_COMPLETE:
            event_ui_process("schema download succ");
            break;

        case IOT_OTA_EVENT_SCHEMA_DONWLOAD_FAIL:
            event_ui_process("schema download fail");
            break;

        // 120 为下载进度事件
        case IOT_FILE_DOWNLOAD_SCHEDULE:
            {
                uint16_t persent = 0;
                persent = *(uint16_t *)(queue_rcv.event_payload);
                USER_API_LOGE("--------------------------->>>>>>>>%d", persent);
                ota_ui_process(fota_running, persent);
            }
            
            break;

        case 0xff: //定时刷新事件
        {
            if(fota_running){
                break;
            } 
            
            // 温湿度 光照强度 读取与RSSI显示
            uint8_t display_buff[20];
            
            // RSSI显示
            sprintf(display_buff, "rssi:%d ", tuya_user_api_rssi_get());
            OLED_DrawStr(64, 46, display_buff);
            OLED_DrawStr(64, 56, "t3324: 2");

            // 温湿度显示
            iot_board_sensor_get_temhum(&nbiot_club_sensor);
            memset(display_buff, 0x00, sizeof(display_buff));
            sprintf(display_buff, "T:%.2f", nbiot_club_sensor.temp_current);
            OLED_DrawStr(9, 36, display_buff);
            memset(display_buff, 0x00, sizeof(display_buff));
            sprintf(display_buff, "H:%.1f", nbiot_club_sensor.humidity_value);
            OLED_DrawStr(9, 46, display_buff);

            //光照强度显示
            OLED_DrawStr(9, 56, "L:357");

            //电量显示
            memset(display_buff, 0x00, sizeof(display_buff));
            sprintf(display_buff, "B:%d %%", iot_board_sensor_get_vbat());
            OLED_DrawStr(80, 1, display_buff);

            //
        }
        break;

        default:
            break;
        }

        OLED_Refresh(); // 刷新缓冲区
    }
}

//将显示内容推送至UI 任务
void iot_board_sensor_display(uint16_t event_id, void* payload, uint16_t payload_len)
{
    iot_board_event_t event;
    event.event_id = event_id;
    event.event_payload = NULL;

    if(payload != NULL){
        event.event_payload = (void*)tal_malloc(payload_len);
        if(event.event_payload != NULL)
        {
            memcpy(event.event_payload, payload, payload_len);
        }
    }

    tal_queue_post(iot_board_sensor_queue, &event, 0);
}

// 获取电池电量，根据分压电阻调整比例
uint8_t iot_board_sensor_get_vbat(void)
{
    INT32_T out_val = 0;        //unit:mv

    //lock resource
    tal_mutex_lock(ty_sensor_mutex);

    TUYA_ADC_BASE_CFG_T cfg = {0};
    cfg.ch_list.data = (1 << 0);
    tkl_adc_init(TUYA_ADC_NUM_0, &cfg);
    tkl_adc_read_single_channel(TUYA_ADC_NUM_0, 0, &out_val);
    tkl_adc_deinit(TUYA_ADC_NUM_0);

    //unlock resource
    tal_mutex_unlock(ty_sensor_mutex);
    //根据实际分压来计算，电阻大小会影响到实际功耗。 目前比例为25%  3M - 1M 
    USER_API_LOGW("adc: %d", out_val);

    /*----4200----2800----*/
    uint8_t vbat_precent =  (out_val/0.25-2800)/(4200-2800)*100;
    USER_API_LOGW("precent: %d", vbat_precent);

    return vbat_precent;
}


// 定时刷新传感器数据
void sensor_timer_timeout(TIMER_ID timer_id, void *data)
{
    // do something!
    iot_board_event_t event;
    event.event_id = 0xff;
    event.event_payload = NULL;
    tal_queue_post(iot_board_sensor_queue, &event, 0);
}


// 读取温湿度传感器数据
void iot_board_sensor_get_temhum(iot_board_sensor * iot_sensor)
{
    uint8_t send_data[3] = {0x2c, 0x0D};
    uint8_t receive_data[8] = {0};

    //lock resource
    tal_mutex_lock(ty_sensor_mutex);

    tkl_i2c_master_send(0, 0x44, (uint8_t *)send_data, 2, 0);
    tkl_i2c_master_receive(0, 0x44, receive_data, 6, 0);
    USER_API_LOGE("rcv: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", receive_data[0], receive_data[1], receive_data[2], receive_data[3], receive_data[4], receive_data[5]);
    iot_sensor->humidity_value = ((float)((receive_data[3] << 8) + receive_data[4])) * 100 / 65535;
    iot_sensor->temp_current = ((float)((receive_data[0] << 8) + receive_data[1])) * 175 / 65535 - 45;
    USER_API_LOGE("T:%.2f H:%.2f", iot_sensor->temp_current, iot_sensor->humidity_value);

    //unlock resource
    tal_mutex_unlock(ty_sensor_mutex);
}

void get_sensor_value(iot_board_sensor * iot_sensor)
{
    if(NULL != iot_sensor){
        memcpy(iot_sensor, &nbiot_club_sensor,sizeof(iot_board_sensor));
    }
}

//UI框架初始化
void iot_board_sensor_ui_create(void)
{

    OLED_DrawStr(6, 1, USER_SW_VER);
    OLED_DrawStr(80, 1, "B:....");
    
    OLED_DrawStr(6, 8, "___________________");
    event_ui_process("  hello tuya !!!");
    OLED_DrawStr(6, 26, "___________________");

    OLED_DrawStr(1, 36, "[");
    OLED_DrawStr(56, 56, "]");

    OLED_DrawStr(64, 36, tuya_user_api_is_dev_binded() ? "bind:yes" : "bind:no");
    OLED_Refresh(); // 刷新缓冲区
}

/**
 * @brief 将BH1750的两个字节数据转换为光照强度值（0-65535）
 * @param dat  —— 存储光照强度的地址（两个字节数组）
 * @retval  成功 —— 返回光照强度值
*/
uint16_t BH1750_Dat_To_Lux(uint8_t* dat)
{
  uint16_t lux = 0;
  lux = dat[0];
  lux <<= 8;
  lux += dat[1];
  lux = (int)(lux / 1.2);
  
  return lux;
}


void iot_board_sensor_init(void)
{

    // uint8_t sen_cmd = 0x10;
    // uint8_t receive_data[8] = {0};
    // tkl_i2c_master_send(0, 0x46, &sen_cmd, 1, 0);
    // tal_system_sleep(200);
    // tkl_i2c_master_receive(0, 0x47, receive_data, 2, 0);
    // USER_API_LOGE("current: %5d lux\n", BH1750_Dat_To_Lux(receive_data));

    iot_board_sensor_timer.autoreload = TAL_TIMER_CYCLE;     // 循环定时器;若使用一次性定时器，定义:TAL_TIMER_ONCE
    iot_board_sensor_timer.period_msecond = 1000 * 2;        // 定时器周期，单位:毫秒
    iot_board_sensor_timer.timeout_cb = sensor_timer_timeout; // 定时回调函数
    iot_board_sensor_timer.arg = NULL;
    tal_sw_timer_create(iot_board_sensor_timer.timeout_cb, iot_board_sensor_timer.arg, &(iot_board_sensor_timer.timerid));
    // 定时器启动：
    tal_sw_timer_start(iot_board_sensor_timer.timerid, iot_board_sensor_timer.period_msecond, iot_board_sensor_timer.autoreload);

    // sample 1:message queue create and send
    tal_queue_create_init(&iot_board_sensor_queue, sizeof(iot_board_event_t), 10);


    int op_ret = tal_mutex_create_init(&ty_sensor_mutex);
    if (OPRT_OK != op_ret) {
        USER_API_LOGE("create mutex fail");
        return;
    }

    THREAD_CFG_T thread_cfg = {
        .priority = TASK_PRIO_EVENT_QUEUE,   // task priority
        .stackDepth = 1024 * 2,              // task stack
        .thrdname = "iot_board_sensor_task", // task name,don't longer than 15
    };
    int ret = tal_thread_create_and_start(&iot_board_sensor_thread, NULL, NULL, iot_board_sensor_task, NULL, &thread_cfg);
}
